package com.futurescale.sa.model.vo
{
	/**
	 * A Scene appears in one Chapter only and groups
	 * a set of Drafts, only one of which may be marked
	 * the 'current draft' of the Scene. This value object 
	 * represents a single Scene and its associated Drafts.
	 */
	[Bindable] 
	public class SceneVO extends ValueObject
	{
		/**
		 * The XML element name.
		 */
		public static const ELEMENT:String = "Scene";
		
		/**
		 * Construct a SceneVO.
		 */
		public function SceneVO( xml:XML=null )
		{
			super( ELEMENT, xml );
			if (xml == null) getNewDraft();
		}
		
		/** 
		 * An ordinal-sorted Vector of this Scene's Drafts.
		 */
		public function get drafts():Vector.<DraftVO>
		{
			var v:Vector.<DraftVO> = new Vector.<DraftVO>();
			var xl:XMLList = xml.child(DraftVO.ELEMENT);
			for each ( var dx:XML in xl ) {
				var draft:DraftVO = new DraftVO(dx);
				v.push(draft);
			}
			v.sort(ValueObject.ordinalSort);
			return v;
		}
		public function set drafts( v:Vector.<DraftVO> ):void
		{} // read-only but bindable
		
		/**
		 * Get the current Draft for this Scene.
		 */
		public function get currentDraft():DraftVO
		{
			var draft:DraftVO;
			for each ( draft in drafts ) {
				if (draft.isCurrent) break;
			}
			return draft;
		}
		public function set currentDraft( dvo:DraftVO ):void
		{
			var draft:DraftVO;
			if (dvo == null) return;
			for each ( draft in drafts ) {
				draft.isCurrent = (draft.uid == dvo.uid);
			}
		}
		
		/**
		 * Get the text of the current Draft of this Scene with optional
		 * heading.
		 */
		public function getText( includeHeading:Boolean=false ):String
		{
			var t:String = includeHeading ? name + DOUBLE_SPACE : "";
			if (currentDraft) t += currentDraft.text;
			
			// read-only text of scene
			return t;
		}
		
		/**
		 * Get a new Draft. 
		 * 
		 * The new draft is a copy of the currentDraft
		 * if it exists. 
		 */
		public function getNewDraft():DraftVO
		{
			var draft:DraftVO = new DraftVO();
			addDraft(draft);
			return draft;
		}
		
		/**
		 * Get a new Draft as a revision of a specific Draft.
		 */
		public function getRevisionDraft( draft:DraftVO ):DraftVO
		{
			var revision:DraftVO = draft.clone(); 
			revision.ordinal = nextDraftOrdinal;
			revision.uid = new DraftVO().uid;
			addDraft(revision);
			return revision;
		}

		/**
		 * Add a Draft to the Scene.
		 */
		public function addDraft( draft:DraftVO ):void
		{
			// renumber drafts if inserting
			if ( draft.ordinal > 0 && draft.ordinal < nextDraftOrdinal ) {
				var drafts:Vector.<DraftVO> = this.drafts;
				for each ( var dvo:DraftVO in drafts ){
					if ( dvo.ordinal >= draft.ordinal ) dvo.ordinal++;
				}
			} else {
				draft.ordinal = nextDraftOrdinal;
			}
			xml.appendChild( draft.xml );
			currentDraft = draft;
		}
		
		/**
		 * Get the next Draft ordinal for this Scene.
		 */
		private function get nextDraftOrdinal():Number
		{
			return getNextOrdinal( xml..Draft );
		}
	}
}